/**
 * Usage: 
 * const version = require('semantic-compare-version');
 * const result = version('1.3.4').greaterThan('1.2.3'); // greaterThan alias to gte
 * // result is boolean
 * console.log(result);
 * 
 * Api:
 * version(currentVersion)
 * .greaterThan(targetVersion);
 * .lowerThan()
 * .greaterThanOrEqual()
 * .lowerThanOrEqual()
 * .equal()
 * .gt()
 * .lt()
 * .gte()
 * .lte()
 * .eq()
 */
module.exports = function compare(currentVersion) {
  const validate = (version) => {
    if (typeof version !== 'string') return false;

    const versionRule = /^v?(?:\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+))?(?:-[\da-z\-]+(?:\.[\da-z\-]+)*)?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i;
    return versionRule.test(version);
  }

  const checkVersion = (version) => {
    if (!validate(version)) throw new Error(`${version} is not a valid version`);
  }

  const _compare = (current, target) => {
    current = current.split('.');
    target = target.split('.');

    for (let i = 0; i < current.length; i++) {
      if (current[i] < target[i]) return -1;
      if (current[i] > target[i]) return 1;
    }
    return 0;
  }

  checkVersion(currentVersion);
    const methods = {
      greaterThan(targetVersion) {
        checkVersion(targetVersion);

        return [1].includes(_compare(currentVersion, targetVersion));
      },

      lowerThan(targetVersion) {
        checkVersion(targetVersion);

        return [-1].includes(_compare(currentVersion, targetVersion));
      },

      greaterThanOrEqual(targetVersion) {
        checkVersion(targetVersion);

        return [0, 1].includes(_compare(currentVersion, targetVersion));
      },

      lowerThanOrEqual(targetVersion) {
        checkVersion(targetVersion);

        return [0, -1].includes(_compare(currentVersion, targetVersion));
      },

      equal(targetVersion) {
        checkVersion(targetVersion);

        return [0].includes(_compare(currentVersion, targetVersion));
      }
    }
    methods.gt = methods.greaterThan;
    methods.lt = methods.lowerThan;
    methods.gte = methods.greaterThanOrEqual;
    methods.lte = methods.lowerThanOrEqual;
    methods.eq = methods.equal;

    return methods;
}